const { ccclass, property } = cc._decorator;

interface viewCell {
    getSize(index: number, data: any, other?: any): cc.Size;
}

interface tvCell extends cc.Node {
    // 当前实际的下标
    tvIndex: number;
    // 将要转变的下标(用于增删操作)
    _tvIndex: number;
}

enum LayoutType {
    Horizontal = 0,
    Vertical = 1
}

enum TableViewEventType {
    SCROLL_TO_START,
    SCROLL_TO_END,
    BOUNCE_START,
    BOUNCE_END,
    TOUCH_UP,
    SCROLL_BEGAN,
    SCROLLING,
    SCROLL_ENDED,
    AUTOSCROLL_ENDED_WITH_THRESHOLD,
}

class ListItem<T> {
    static create<T>(data?: T) {
        return new ListItem(data)
    }

    public data: T = null;

    public next: ListItem<T> = null;
    public last: ListItem<T> = null;

    constructor(data?: T) {
        this.data = data;
    }

    destroy() {
        this.data = null;
        this.next = null;
        this.last = null;
    }
}

class List<T> {
    static create<T>(array?: T[]) {
        return new List(array);
    }

    private arrayCache: Array<T> = null;
    private count: number = 0;
    private head: ListItem<T> = null;
    private tail: ListItem<T> = null;

    private createResult: ListItem<T>[] = [];
    private create(array: T[]) {
        this.createResult[0] = null;
        this.createResult[1] = null;

        let item: ListItem<T> = null;
        array.forEach((data, index) => {
            if (index === 0) {
                item = this.createResult[0] = ListItem.create(data);
            } else {
                item.next = ListItem.create(data);
                item.next.last = item;
                item = item.next;
            }
            this.createResult[1] = item;
        })
    }

    constructor(array?: T[]) {
        if (!array) return;
        this.create(array);
        this.count = array.length;
        this.head = this.createResult[0];
        this.tail = this.createResult[1];
    }

    get array() {
        if (this.arrayCache) return this.arrayCache;

        const result = [];
        this.each(function (item) {
            result.push(item.data);
        })

        this.arrayCache = result;
        return result;
    }

    get length() {
        return this.count;
    }

    each(callback: (item: ListItem<T>, index: number) => any) {
        let item = this.head;
        let next = null;
        let index = 0;
        while (item) {
            next = item.next;
            if (callback(item, index) === false) break;
            item = next;
            ++index;
        }
    }

    reverseEach(callback: (item: ListItem<T>, index: number) => any) {
        let item = this.tail;
        let last = null;
        let index = this.count - 1;
        while (item) {
            last = item.last;
            if (callback(item, index) === false) break;
            item = last;
            --index;
        }
    }

    /**
     * 找到index对应的item
     */
    get(index: number = 0): ListItem<T> {
        if (index >= this.count) return;
        if (index < -this.count) return;

        let item: ListItem<T> = index >= 0 ? this.head : this.tail;
        if (!item) return;


        let prop = index >= 0 ? 'next' : 'last';
        let loop = index >= 0 ? index : -index - 1;
        for (let i = 0; i < loop; ++i) {
            item = item[prop];
        }

        return item;
    }

    /**
     * 找到index对应的item，若超出边界则返回边界值
     */
    private _get(index: number = 0): ListItem<T> {
        const item = this.get(index);
        if (item) return item;
        if (index >= 0) return this.tail;
        return this.head;
    }

    remove(index: number = -1, count: number = 1) {
        if (count <= 0) return;

        // 找到index对应的item，若超出边界则返回边界值
        let item: ListItem<T> = this._get(index);

        // next指向当前index对应的item
        // 最终next指向下一个有效item(next可能为null)
        let next: ListItem<T> = item;
        for (let i = 0; i < count; ++i) {
            if (next) {
                next = next.next;
            } else {
                break;
            }
        }

        // 连接item
        if (item === this.head) {
            this.head = next;
            next.last = null;
        } else if (next) {
            next.last = item.last;
            item.last.next = next;
        } else {
            item.last.next = null;
        }

        // 销毁被断开的item
        while (item) {
            next = item.next;
            item.destroy();
            item = next;
        }

        this.arrayCache = null;
    }

    insert(index: number = -1, data: T[]) {
        if (data.length === 0) return;

        this.create(data);
        let head: ListItem<T> = this.createResult[0];
        let tail: ListItem<T> = this.createResult[1];

        // 找到index对应的item，若超出边界则返回边界值
        let item: ListItem<T> = this._get(index);

        // 连接item
        if (item === this.head) {
            tail.next = this.head;
            this.head.last = tail;

            this.head = head;
        } else {
            head.last = item.last;
            item.last.next = head;

            item.last = tail;
            tail.next = item;
        }

        this.count += data.length;
        this.arrayCache = null;
    }

    clear() {
        this.each(function (item) {
            item.destroy();
        })

        this.arrayCache = null;
        this.head = null;
        this.tail = null;
        this.count = 0;
    }

    init(data: T[]) {
        this.clear();
        this.insert(-1, data);
    }
}

@ccclass
export default class tableView2 extends cc.Component {
    static EventType = cc.Enum(TableViewEventType)

    @property
    private _container: cc.Node = null;
    @property({ type: cc.Node, tooltip: '渲染节点的容器(默认当前节点)' })
    get container() { return this._container || this.node; }
    set container(value) {
        this._container = value;
    }

    @property
    private _cell: cc.Prefab = null;
    @property({ type: cc.Prefab, tooltip: '渲染节点预制体' })
    get cell() { return this._cell; }
    set cell(value) {
        this._cell = value;
    }

    @property
    private _horizontal: boolean = false;
    @property({ tooltip: '是否开启水平滚动' })
    get horizontal() { return this._horizontal; };
    set horizontal(value) {
        this._horizontal = value;
    };

    @property
    private _vertical: boolean = true;
    @property({ tooltip: '是否开启垂直滚动' })
    get vertical() { return this._vertical; };
    set vertical(value) {
        this._vertical = value;
    };

    @property
    private _layoutType: LayoutType = LayoutType.Vertical;
    @property({ type: cc.Enum(LayoutType), tooltip: '排列方向' })
    get layoutType() { return this._layoutType; }
    set layoutType(value) {
        this._layoutType = value;
    }

    @property
    private _trackCount: number = 1;
    @property({ tooltip: 'Horizontal: 有几行\nVertical: 有几列' })
    get trackCount() { return this._trackCount; }
    set trackCount(value) {
        this._trackCount = Math.max(Math.floor(value), 1);
    }

    @property({ tooltip: '是否开启惯性滚动' })
    inertia: boolean = true;

    @property({
        tooltip: '开启惯性滚动后，用户手指离开后，多快停止。0表示永不停止，1表示立即停止',
        range: [0, 1],
        visible() { return this.inertia }
    })
    brake: number = 0.75;

    @property({ tooltip: '是否允许滚动内容超出边界，并在停止触摸后进行回弹' })
    elastic: boolean = true;

    @property({
        tooltip: '回弹持续时间，小于等于0表示立即回弹',
        visible() { return this.elastic }
    })
    bounceDuration: number = 0.23;

    // cell节点池
    private cellPool: cc.NodePool = new cc.NodePool('viewCell');
    // cell节点List
    private cellList: List<tvCell> = List.create();
    // cell数据的List
    private dataList: List<any> = List.create();
    // 其他数据
    private otherData: any = null;

    // 是否滚动中
    private scrolling: boolean = false;
    // 当前开始下标
    private beganIndex: cc.Vec2 = cc.v2(0, 0);
    // 当前结束下标
    private endedIndex: cc.Vec2 = cc.v2(0, 0);

    // 是否自定义大小
    private isCustomSize: boolean = false;
    // cell默认大小
    private cellDefSize: cc.Size = cc.Size.ZERO;
    private anchorCenterX: number = 0;
    private anchorCenterY: number = 0;
    private anchorLeftX: number = 0;
    private anchorTopY: number = 0;
    private cellAnchorX: number = 0;
    private cellAnchorY: number = 0;

    // 向上，向右 为正方向
    private scrollLen: cc.Vec2 = cc.v2(0, 0);

    /**
     * 获得cell上绑定的脚本组件
     */
    private getViewCell(): viewCell {
        if (this.cell) {
            const com = this.cell.data.getComponent('viewCell');
            if (com) {
                // return <typeof viewCell>cc.js.getClassByName(cc.js.getClassName(com));
                return com.constructor || cc.js.getClassByName(cc.js.getClassName(com));
            }
        }
        return null;
    }

    private hasViewCellSize(): boolean {
        const cell = this.getViewCell();
        return !!cell && !!cell.hasOwnProperty('getSize');
    }

    private getViewCellSize(index: number): cc.Size {
        const cell = this.getViewCell();
        return this.hasViewCellSize() ? cell.getSize(index, this.dataList.array[index], this.otherData) : this.cellDefSize;
    }

    /**
     * 获取默认cell大小
     */
    private getDefaultCellSize() {
        if (this.cell) {
            if (CC_DEBUG && this.cell.data.getComponent(cc.Widget)) {
                cc.warn('[tableView] cell根节点中存在cc.Widget，可能无法正确获取Size');
            }
            return this.cell.data.getContentSize();
        }
        return cc.Size.ZERO;
    }

    /**
     * 获取默认cell锚点
     */
    private getDefaultCellAnchor() {
        if (this.cell) {
            return this.cell.data.getAnchorPoint();
        }
        return cc.Vec2.ZERO;
    }

    private getCell(): tvCell {
        let node: tvCell = null;
        if (this.cellPool.size()) {
            node = <tvCell>this.cellPool.get();
        } else {
            node = <tvCell>cc.instantiate(this.cell);
        }
        node.tvIndex = -1;
        node._tvIndex = -1;
        return node;
    }

    private putCell(node: tvCell) {
        this.cellPool.put(node);
    }

    private initCell(cell: tvCell, index: number) {
        if (index >= 0) {
            if (cell.tvIndex != index || cell.tvIndex != cell._tvIndex) {
                const com = cell.getComponent('viewCell');
                if (cell.tvIndex >= 0) com.uninit();
                com.init(index, this.dataList.array[index], this.otherData, this);
            }
            cell.tvIndex = index;
            cell._tvIndex = index;
        }
    }

    private uninitCell(cell: tvCell) {
        if (cell.tvIndex >= 0) {
            cell.getComponent('viewCell').uninit();
            cell.tvIndex = -1;
            cell._tvIndex = -1;
        }
    }

    /**
     * 更新开始下标、结束下标、childNum
     */
    private updateCellRange() {
        // float
        const xStartIndex = this.beganIndex.x;
        const yStartIndex = this.beganIndex.y;
        // int
        const trackCount = this.trackCount;
        const conHeight = this.container.height;
        const conWeight = this.container.width;

        let xCount = 0;
        let yCount = 0;

        // 竖向排列
        if (this.layoutType === LayoutType.Vertical) {
            const cellSize = this.getViewCellSize(Math.floor(yStartIndex));
            const width = cellSize.width;
            const height = cellSize.height;




            if (this.horizontal) {

            } else if (this.vertical) {

            }
        } 
        // 横向排列
        else {
            if (this.horizontal) {

            } else if (this.vertical) {

            }
        }
    }

    /**
     * 更新cell的数量，不够添加，多了删除
     */
    private updateCellCount() {
        const xStartIndex = 0;
        const yStartIndex = 0;
    }

    /**
     * 更新cells状态
     */
    private updateCells() {

        this.updateCellRange();
        this.updateCellCount();

        const trackCount = this.trackCount;
        const prop = this.layoutType === LayoutType.Vertical ? 'height' : 'width';
        // this.isCustomSize ? this.getViewCellSize(this.layoutType === LayoutType.Vertical ? this.beganIndex.y : this.beganIndex.x) : this.cellDefSize[prop];

        // 一帧的移动距离
        const xScrollLen = this.scrollLen.x;
        const yScrollLen = this.scrollLen.y;

        if (xScrollLen <= 0) {
            // 向左

        } else {
            // 向右

        }

        if (yScrollLen >= 0) {
            // 向上

        } else {
            // 向下

        }

        const xIndex = Math.floor(xScrollLen);
        const xProgress = xScrollLen - xIndex;

        const yIndex = Math.floor(yScrollLen);
        const yProgress = yScrollLen - yIndex;


        const cellSize = this.isCustomSize ? this.getViewCellSize(this.layoutType === LayoutType.Vertical ? yIndex : xIndex) : this.cellDefSize;

        // 开始下标
        const xStartIndex = xIndex * trackCount;
        const yStartIndex = yIndex * trackCount;


        this.scrollLen.x = 0;
        this.scrollLen.y = 0;
    }

    /**
     * 初始化基础数据
     */
    private initBasicsData() {
        // 初始cell大小
        this.cellDefSize = this.getDefaultCellSize();

        // 是否自定义大小
        this.isCustomSize = this.hasViewCellSize();

        // 计算基础定位数值
        const cellAnchor = this.getDefaultCellAnchor();
        this.anchorCenterX = (0.5 - this.container.anchorX) * this.container.width;
        this.anchorCenterY = (0.5 - this.container.anchorY) * this.container.height;
        this.anchorLeftX = (0 - this.container.anchorX) * this.container.width;
        this.anchorTopY = (1 - this.container.anchorY) * this.container.height;
        this.cellAnchorX = cellAnchor.x;
        this.cellAnchorY = 1 - cellAnchor.y;
    }

    /**
     * 初始化
     */
    initWithCount(count: number, other?: any) {
        return this.init(Array(count), other);
    }

    /**
     * 初始化
     */
    init(data: any[], other?: any) {
        if (CC_DEBUG) {
            if (!this.cell) {
                return cc.error('[tableView] 请指定cell');
            }
            if (!this.getViewCell()) {
                return cc.error('[tableView] 请在cell中添加继承自<viewCell>的自定义组件');
            }
        }
        this.clear();

        this.dataList.init(data);
        this.otherData = other;

        this.initBasicsData();

        this.updateCells();
    }

    /**
     * 重载
     */
    reload(start = 0, count?: number) {

    }

    /**
     * 清空
     */
    clear() {
        this.cellList.each((item) => {
            this.uninitCell(item.data);
            this.putCell(item.data);
        })
        this.cellList.clear();
        this.dataList.clear();
    }

    /**
     * 插入
     */
    insert(start = -1, count = 1, data?: any) {

    }

    /**
     * 删除
     */
    remove(start = -1, count = 1, data?: any) {

    }

    scrollTo(progress: number = 0) {

    }

    scrollToStart() {
        this.scrollTo(0);
    }

    scrollToEnd() {
        this.scrollTo(-1);
    }

    stopAutoScroll() {

    }

    private autoScroll(dt: number) {
        if (this.scrolling === false) return;
    }

    update(dt: number) {
        this.autoScroll(dt);

        // if (this.updateRefreshOnce) this.refreshSync(this.updateRefreshForce);
        // if (this.updateCellsOn || this.updateCellsOnce) this.updateCells();
    }
}
